# -*- coding: utf-8 -*-

from __future__ import absolute_import

from collections import deque
import random

import tornado.ioloop

from fullsteam import json
from fullsteam import mapgen

VIEWER = []
POSITIONS = ['shovel', 'shake', 'swipe'] # , 'image_quiz']
FIX_POS = None # 'shake'


def write_viewers(msg):
    for viewer in VIEWER:
        viewer.write_message(msg)


class Game(json.JSONable):
    _json_attrs = ('score', 'inputs', 'train_speed', 'coal', 'gameover')

    def __init__(self):
        self.score = 0
        self.inputs = []
        self.gameover = False
        self.mapgen = None
        self.reset()

    def to_jsonable(self):
        data = json.JSONable.to_jsonable(self)
        data['lines'] = json.to_jsonable(self._new_lines)
        self._new_lines = []
        return data

    def reset(self):
        do_reload = self.gameover
        self.random = random.Random()
        self.unstaffed = POSITIONS
        self.gameover = False

        self.time = 0

        self.train_speed = 0 # px per second
        self.to_slow = 0
        self.pressure = 200
        self.tile = 0
        self.pos = 0
        self.coal_state = 150

        if not self.mapgen or do_reload:
            self._lines = deque()
            self._new_lines = []
            self.mapgen = mapgen.MapGenerator(self, random.Random(self.random.randint(0, 10000)))
            # start map
            for i in xrange(15):
                self.gen_line()
        if do_reload:
            write_viewers({'reload': True})

    @property
    def coal(self):
        state = self.coal_state / 100
        if state >= 3:
            state = 2
        elif state < 0:
            state = 0
        return ['k1', 'm1', 'g1'][state]

    def start(self):
        self.reset()
        print '--- start game ---'
        self.distribute_positions()
        for viewer in VIEWER:
            viewer.last_data = {}
        try:
            self.callback = tornado.ioloop.PeriodicCallback(self.tick, 100)
            self.callback.start()
        except:
            pass

    def stop(self):
        self.callback.stop()
        self.train_speed = 0
        for input in self.inputs:
            if input.position:
                input.call('end_game')
                input.is_ready = False
        for viewer in VIEWER:
            viewer.last_data = {}

    def tick(self):
        # main game loop, ticks every 100 ms
        self.time += 100

        if self.gameover:
            self.train_speed -= 2
            if self.train_speed <= 0:
                self.stop()
            return

        # reduce coal state
        if self.coal_state > 0:
            self.coal_state -= 5
        if 'shovel' in self.unstaffed:
            # there is nobody for the shovel - so we auto adjust it
            if self.train_speed < 150:
                # we are to slow!
                self.coal_state = 210
                #if self.coal_state < 210:
                #    self.coal_state += 1
                #elif self.coal_state > 210:
                #    self.coal_state -= 1
            elif self.train_speed > 150:
                # we are to fast
                self.coal_state = 90
                #if self.coal_state < 90:
                #    self.coal_state += 1
                #elif self.coal_state > 90:
                #    self.coal_state -= 1
            else:
                self.coal_state = 150
                # keep this pace
                #if self.coal_state < 150:
                #    self.coal_state += 1
                #elif self.coal_state > 150:
                #    self.coal_state -= 1

#         self.train_speed += 1
        if self.coal_state < 100:
            if self.train_speed > 0: # at the beginning we might go backwards if we don;'t check here
                self.train_speed -= 4
        elif self.coal_state >= 200:
            self.train_speed += 4

        if self.time > 10000: # we don't care about speed in the first 10 sec
            if self.train_speed <= 25:
                self.to_slow += 1
                if self.to_slow > 50:
                    self.over('zu langsam')
                write_viewers({'message': 'schneller!!!', 'duration': 5000})
            elif self.train_speed <= 75:
                self.to_slow = 0
                if self.time % 5000 == 0:
                    write_viewers({'message': 'schneller', 'duration': 5000})
            elif self.train_speed >= 175:
                self.to_slow = 0
                if self.time % 5000 == 0:
                    write_viewers({'message': 'langsamer', 'duration': 5000})
                self.train_speed = 175
            #elif self.train_speed >= 300:
            #    self.over('zu schnell')
        print 'speed', self.train_speed, 'coal', self.coal_state

    def over(self, text='GAME OVER'):
        self.gameover = True
        write_viewers({'message': text, 'duration': 60000})

    def gen_line(self):
        new_line = self.mapgen.next()
        self._lines.append(new_line)
        self._new_lines.append(new_line)

    def new_input(self, input):
        self.inputs.append(input)
        for viewer in VIEWER:
            viewer.write_message({'message': 'new player ' + input.username, 'duration': 5000})

    def distribute_positions(self):
        open_positions = POSITIONS[:]
        for input in self.inputs:
            if open_positions:
                if FIX_POS:
                    input.position = FIX_POS
                else:
                    input.position = random.choice(open_positions)
                input.call('start_game', input.position, False)
                open_positions.remove(input.position)
        self.unstaffed = open_positions

    def check_go(self):
        print 'go?', [input.is_ready for input in self.inputs]
        if all(input.is_ready for input in self.inputs):
            self.start()

    def lost_input(self, input):
        for viewer in VIEWER:
            viewer.write_message({'message': 'goodbye ' + input.username, 'duration': 5000})
        self.inputs.remove(input)

    def line_done(self, done_id):
        while self._lines[0].id < done_id:
            line = self._lines.popleft()
            print 'passing line', line
            line.check_done(self)
            self.gen_line()
            self.score += self.train_speed


GAME = Game()
